#pragma once
#include "stdafx.h"
#include "Identifier.h"

	class Component;
	class Object;
	class Manager;

	struct ComponentRequest;
	struct Message;
	struct RegisteredComponent;
	struct RequestLock;

	enum ComponentRequestType 
	{
		REQ_COMPONENT = 0,
		REQ_MESSAGE = 1
	};

	enum MessageType 
	{
		CREATE,
		DESTROY,
		MESSAGE
	};

	union RequestId
	{
		RequestId(MsgId m):msg(m){}
		RequestId(CompName c):comp(c){}
		MsgId msg;
		CompName comp;
	public:
		operator int(void) const
		{
			return (int)msg;
		}

		bool operator == (const RequestId& id) const
		{
			return msg==id.msg;
		}

		void operator = (const RequestId& id)
		{
			msg=id.msg;
		}
	};

	std::size_t hash_value(const RequestId& id);

	typedef boost::shared_ptr<Component> CompPtr;
	typedef boost::shared_ptr<Object> ObjPtr;
	typedef boost::shared_ptr<Manager> ManagerPtr;
	typedef int CompId;
	typedef boost::function<void(Message const &)> MessageFunction;
	typedef list<RegisteredComponent> CallbackList;
	typedef Vector< CompPtr > CompPtrVector;
	typedef boost::unordered_map< CompId, CompPtr, boost::hash<int> > CompMap;
	typedef boost::unordered_map< RequestId,CallbackList, boost::hash<RequestId>> Requests;
	typedef boost::unordered_map< ComponentRequestType, Requests , boost::hash<int> > RequestMap;
	typedef boost::unordered_map< RequestId, RequestLock, boost::hash<RequestId> > Locks;
	typedef boost::unordered_map< ComponentRequestType, Locks ,boost::hash<int> > LockMap;
	
#define REQ_MSG(m) ComponentRequest(REQ_MESSAGE,RequestId(m))
#define REQ_COMP(c) ComponentRequest(REQ_COMPONENT,RequestId(c))
#define MSG_INFO(t,p) Message(MESSAGE,t,p)
#define MSG_NOCOMP(p) Message(MESSAGE,p)
#define MSG_COMP(id,c) Message(CREATE,id,AuxGroupArgus(c))

	struct ComponentRequest 
	{
		ComponentRequestType type;
		RequestId id;
		ComponentRequest(ComponentRequestType t, RequestId _id) : type(t), id(_id) {};
		bool operator == (const ComponentRequest& tmp) const
		{
			return type==tmp.type && id == tmp.id;
		}

		void operator = (const ComponentRequest& tmp)
		{
			type=tmp.type;
			id=tmp.id;
		}
	};

	struct Message 
	{
		MessageType type;
		CompId sender;
		boost::any p;
		Message(MessageType t, boost::any payload) : type(t), p(payload) {};
		Message(MessageType t, CompId c, boost::any payload) : type(t), sender(c), p(payload) {};
	};

	// a component registered for an event (message or component creation/destruction)
	struct RegisteredComponent 
	{
		CompId cid;
		MessageFunction callback;
		RegisteredComponent(CompId _c,MessageFunction _f):cid(_c),callback(_f){}
		bool operator == (const RegisteredComponent& tmp) const;
	};

	struct RequestLock 
	{
		bool locked;
		list<pair<ComponentRequest, RegisteredComponent> > pendingLocalRequests;
		list<pair<ComponentRequest, RegisteredComponent> > pendingGlobalRequests;
		RequestLock() : locked(false) {};
	};

#include "Component.h"
#include "Object.h"
#include "Manager.h"